import {hasChange, isArray, isObject} from "../utils";
import {track, trigger} from "./effect";

// 对象复用 a=reactive(obj), b=reactive(obj) 不用再去新创建
const proxyMap = new WeakMap();
export function reactive(target){
    if (!isObject(target)){return target;}
    // 是Reactive就返回
    if(isReactive(target)){return target;}
    // 如果之前创建过 就返回回去
    if (proxyMap.has(target)) return proxyMap.get(target);
    const proxy = new Proxy(target, {
        get(target, key, receiver) {
            // 标记已是 Reactive 化的对象
            if (key === '__isReactive'){
                return true;
            }
            const res = Reflect.get(target, key, receiver);
            track(target, key);
            // 懒加载深层的对象，用到的时候再生成 reactive
            return isObject(res) ? reactive(res) : res;
        },
        set(target, key, value, receiver) {
            let oldLength = target.length; // 这一条兼顾数组用的
            const oldValue = target[key];
            const res = Reflect.set(target, key, value, receiver);
            // 判断值是否改变了。
            if (hasChange(oldValue, value)){
                trigger(target, key);
                // 如果数组长度改变了
                if (hasChange(oldLength, target.length) && isArray(target)) {
                    trigger(target, 'length');
                }
            }
            return res;
        }
    });
    // 保存起来，就不会重复创建同类型的Reactive了
    proxyMap.set(target, proxy);
    return proxy;
}
// 如果是 Reactive 对象就不再 Proxy 化
export function isReactive (target){
    return !!(target && target.__isReactive);
}